/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include "dal/domain_participant.h"
#include "dal/subscriber.h"
#include "dal/topic.h"
#include "dal_rticonnextdds/converter/QosConverter.hpp"
#include "mj_interfaces/msg/mjtype.hpp"

TEST(sub_create_and_delete, test_subscriber)
{
    dal_ret_t ret;
    dal_domain_participant_listener_callbacks_t participant_callbacks = { };

    dal_domain_participant_listener_t* participant_listener =
        dal_create_domain_participant_listener(participant_callbacks);

    dal_domain_participant_t* participant = dal_create_domain_participant(
        20, DAL_PARTICIPANT_QOS_DEFAULT, participant_listener, DAL_ANY_STATUS);

    dal_subscriber_listener_callbacks_t sub_callbacks = { };

    dal_subscriber_listener_t* sub_listener = dal_create_subscriber_listener(sub_callbacks);

    dal_subscriber_t* sub = dal_domain_participant_create_subscriber(
        participant, DAL_SUBSCRIBER_QOS_DEFAULT, sub_listener, DAL_ANY_STATUS);
    EXPECT_NE(sub->handle_, nullptr);

    ret = dal_delete_subscriber_listener(sub_listener);
    EXPECT_EQ(ret, DAL_RETCODE_PRECONDITION_NOT_MET);

    ret = dal_domain_participant_delete_subscriber(participant, sub);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_delete_subscriber_listener(sub_listener);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_delete_domain_participant(participant);

    dal_delete_domain_participant_listener(participant_listener);
}

TEST(datareader_create_and_delete, test_subscriber)
{
    dal_ret_t ret;
    dal_domain_participant_listener_callbacks_t participant_callbacks = { };

    dal_domain_participant_listener_t* participant_listener =
        dal_create_domain_participant_listener(participant_callbacks);

    dal_domain_participant_t* participant = dal_create_domain_participant(
        20, DAL_PARTICIPANT_QOS_DEFAULT, participant_listener, DAL_ANY_STATUS);

    dal_subscriber_listener_callbacks_t sub_callbacks = { };

    dal_subscriber_listener_t* sub_listener = dal_create_subscriber_listener(sub_callbacks);

    dal_subscriber_t* sub = dal_domain_participant_create_subscriber(
        participant, DAL_SUBSCRIBER_QOS_DEFAULT, sub_listener, DAL_ANY_STATUS);

    dal_type_support_t* ts =
        dal_create_type_support((void*)(mj_interfaces::msg::Mjtype::FullyQualifiedName()));

    const char* type_name = dal_type_support_get_type_name(ts);
    ret = dal_type_support_register_type(ts, participant, type_name);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_topic_listener_callbacks_t topic_callbacks = { };

    dal_topic_listener_t* topic_listener = dal_create_topic_listener(topic_callbacks);

    dal_topic_t* topic = dal_domain_participant_create_topic(participant,
                                                             "HelloWorldTopic",
                                                             type_name,
                                                             DAL_TOPIC_QOS_DEFAULT,
                                                             topic_listener,
                                                             DAL_NONE_STATUS);

    dal_datareader_listener_callbacks_t reader_callbacks = { };
    memset(&reader_callbacks, 0, sizeof(reader_callbacks));

    dal_datareader_listener_t* reader_listener = dal_create_datareader_listener(reader_callbacks);

    dal_datareader_t* reader = dal_subscriber_create_datareader(
        sub, topic, DAL_DATAREADER_QOS_DEFAULT, reader_listener, DAL_ANY_STATUS);
    EXPECT_NE(reader->handle_, nullptr);

    ret = dal_delete_datareader_listener(reader_listener);
    EXPECT_EQ(ret, DAL_RETCODE_PRECONDITION_NOT_MET);

    ret = dal_subscriber_delete_datareader(sub, reader);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    ret = dal_delete_datareader_listener(reader_listener);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_domain_participant_delete_topic(participant, topic);
    dal_delete_topic_listener(topic_listener);
    dal_delete_type_support(ts);
    dal_domain_participant_delete_subscriber(participant, sub);
    dal_delete_subscriber_listener(sub_listener);
    dal_delete_domain_participant(participant);
    dal_delete_domain_participant_listener(participant_listener);
}

TEST(sub_and_reader_created_with_created_default_qos, test_publisher)
{
    dal_ret_t ret;

    dal_domain_participant_qos_t* part_qos = dal_create_default_participant_qos();
    dal_subscriber_qos_t* sub_qos = dal_create_default_subscriber_qos();
    dal_datareader_qos_t* reader_qos = dal_create_default_datareader_qos();

    dal_domain_participant_t* participant =
        dal_create_domain_participant(20, part_qos, NULL, DAL_ANY_STATUS);

    dal_subscriber_t* sub =
        dal_domain_participant_create_subscriber(participant, sub_qos, NULL, DAL_ANY_STATUS);

    dal_type_support_t* ts =
        dal_create_type_support((void*)(mj_interfaces::msg::Mjtype::FullyQualifiedName()));
    const char* type_name = dal_type_support_get_type_name(ts);
    ret = dal_type_support_register_type(ts, participant, type_name);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_topic_t* topic = dal_domain_participant_create_topic(
        participant, "HelloWorldTopic", type_name, DAL_TOPIC_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    dal_datareader_t* reader =
        dal_subscriber_create_datareader(sub, topic, reader_qos, NULL, DAL_ANY_STATUS);

    EXPECT_NE(reader->handle_, nullptr);
    ret = dal_subscriber_delete_datareader(sub, reader);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
    dal_domain_participant_delete_topic(participant, topic);
    dal_delete_type_support(ts);
    dal_domain_participant_delete_subscriber(participant, sub);
    dal_delete_domain_participant(participant);

    dal_delete_participant_qos(part_qos);
    dal_delete_subscriber_qos(sub_qos);
    dal_delete_datareader_qos(reader_qos);
}

TEST(datareader_take_sample_directly, test_publisher)
{
    dal_ret_t ret;

    dal_domain_participant_t* participant =
        dal_create_domain_participant(20, DAL_PARTICIPANT_QOS_DEFAULT, NULL, DAL_ANY_STATUS);
    dal_subscriber_t* sub = dal_domain_participant_create_subscriber(
        participant, DAL_SUBSCRIBER_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    dal_type_support_t* ts =
        dal_create_type_support((void*)(mj_interfaces::msg::Mjtype::FullyQualifiedName()));
    const char* type_name = dal_type_support_get_type_name(ts);
    ret = dal_type_support_register_type(ts, participant, type_name);
    EXPECT_EQ(ret, DAL_RETCODE_OK);

    dal_topic_t* topic = dal_domain_participant_create_topic(
        participant, "HelloWorldTopic", type_name, DAL_TOPIC_QOS_DEFAULT, NULL, DAL_ANY_STATUS);

    dal_datareader_t* reader = dal_subscriber_create_datareader(
        sub, topic, DAL_DATAREADER_QOS_DEFAULT, NULL, DAL_ANY_STATUS);
    EXPECT_NE(reader->handle_, nullptr);

    dal_sample_info info;
    mj_interfaces::msg::Mjtype msg;

    ret = dal_datareader_take_next_sample(reader, &msg, &info);
    EXPECT_EQ(ret, DAL_RETCODE_NO_DATA);

    ret = dal_subscriber_delete_datareader(sub, reader);
    EXPECT_EQ(ret, DAL_RETCODE_OK);
    dal_domain_participant_delete_topic(participant, topic);
    dal_delete_type_support(ts);
    dal_domain_participant_delete_subscriber(participant, sub);
    dal_delete_domain_participant(participant);
}